To measure the ideological content of several major online news services, I compare the topics discussed in these media with the press releases of the Bundestag parties using a structural topic model.

The following is an analysis of the content of the press releases scraped from the public websites of the political parties and political groups. A big part of this analysis is inspired from the work of Julia Silge and David Robinson (Text Mining with R - A Tidy Approach).

I assume that parties utilize their press releases to promote their issues and positions and thus also contribute to the election campaign. However, it should be noted that there is a difference between the press releases of the parties and the factions. Parties are financed by membership dues, donations and campaign expenses, while factions are financed by state funds. According to Parteigesetzt §25 (2) state funded factions may not support parties from their funds, because otherwise parties that are not in the Bundestag would be practically disadvantaged.

Since it is difficult to draw the line between faction activity and election campaign assistance, I assume that factions intervene in the public perception of this party with their press releases, which is why I include both the press releases of the federal party and the federal faction.

Load Data

CDU

FDP

B90 / Die Grünen

Clean Data

  1. Remove…
  1. Stemming
title_text text_cleaned
327 Rücktritt Agramunts war überfällig Der Europarat wird von einem Korruptionsskandal erschüttert. Mit dem Rücktritt des Präsidenten der Versammlung Pedro Agramunt tritt eine der Hauptfiguren eines Netzwerks zum Schutz Aserbaidschans zurück. Nachdem bereits der ehemalige Vorsitzende der Fraktion der Europäischen Volkspartei Luca Volontè überführt wurde, Millionensummen aus Aserbaidschan erhalten zu haben, und nach dem Rücktritt von Aserbaidschan-Lobbyist Alain Destexhe erreicht die Rücktritts- und Enthüllungswelle einen vorläufigen, traurigen Höhepunkt. „Jetzt müssen auch deutsche Abgeordnete Konsequenzen ziehen. Die Bundestagsabgeordnete Karin Strenz, die finanzielle Zuwendungen aus Aserbaidschan bereits zugegeben hat, und der ehemalige Staatssekretär Eduard Lintner, der als Geldverteiler und Oberlobbyist fungiert hat, sind offenbar ebenfalls an führender Stelle beteiligt. Auch der jetzige Leiter der Deutschen Delegation und Fraktionsvorsitzende der Europäischen Volkspartei Axel Fischer gehört offenbar zumindest zum Unterstützer-Netzwerk Aserbaidschans und anderer autoritär regierter Länder Europas. Der Rücktritt von Karin Strenz als Mitglied der Parlamentarischen Versammlung des Europarats und als Bundestagsabgeordnete ist überfällig. Die CDU/CSU-Bundestagsfraktion muss endlich Konsequenzen ziehen. Der Europarat hat nur dann eine Chance als wichtige Institution zur Verteidigung der Menschenrechte, Demokratie und Rechtsstaatlichkeit, wenn ohne Ansehen der Person schonungslos aufgeklärt wird und neue Regeln geschaffen werden, um Korruption in Zukunft zu unterbinden. Dazu dient unter anderem eine Untersuchungskommission des Europarats. Das reicht aber nicht. Auch die nationalen Parlamente, wie der Deutsche Bundestag, müssen alles in ihrer Macht stehende tun, um aktuell aufzuklären und zukünftige Skandale zu verhindern. Dazu gehören auch ein Lobbyregister und eine Ausweisung von Nebeneinkünften auf ‘Heller und Pfennig‘.“ rücktritt agramunts überfällig europarat korruptionsskandal erschüttert rücktritt präsidenten versammlung pedro agramunt tritt hauptfiguren netzwerks schutz aserbaidschans ehemalige vorsitzende europäischen volkspartei luca volontè überführt millionensummen aserbaidschan rücktritt aserbaidschan lobbyist alain destexhe erreicht rücktritts enthüllungswelle vorläufigen traurigen höhepunkt deutsche abgeordnete konsequenzen karin strenz finanzielle zuwendungen aserbaidschan zugegeben ehemalige staatssekretär eduard lintner geldverteiler oberlobbyist fungiert offenbar führender stelle beteiligt jetzige leiter deutschen delegation europäischen volkspartei axel fischer gehört offenbar unterstützer netzwerk aserbaidschans autoritär regierter länder europas rücktritt karin strenz mitglied parlamentarischen versammlung europarats überfällig endlich konsequenzen europarat chance wichtige institution verteidigung menschenrechte demokratie rechtsstaatlichkeit ansehen person schonungslos aufgeklärt regeln geschaffen korruption zukunft unterbinden dient untersuchungskommission europarats reicht nationalen parlamente deutsche bundestag stehende aktuell aufzuklären zukünftige skandale verhindern gehören lobbyregister ausweisung nebeneinkünften heller pfennig

Inspect Data

Tokens

tokens <- pressReleases %>% unnest_tokens(word, text_cleaned1)

tokens.count <- tokens %>%
  count(party, word, sort = TRUE) %>%
  ungroup() %>%
  bind_tf_idf(word,party,n)

Compare the word frequency for the different parties.

  • an empty space at low frequency indicates less similarity between two parties.

  • if words in a two-sided panel are closer to the zero-slope line the two parties use more similar words.

frequency <- tokens.count %>%
  group_by(party) %>%
  mutate(proportion = n/sum(n)) %>%
  select(party, word, proportion) %>%
  spread(party, proportion) 

CDU

SPD

FDP

B90/GRÜNE

DIE LINKE

AfD

TF-IDF

The statistic tf-idf (term frequency - inverse document frequency) is intended to measure how important a word is to a document in a collection (or corpus) of documents. In this case we measure how important a word is to a party (within all the press releases of that party) in the collection of all parties (and their press releases).

The inverse document frequency for any given term is defined as

\[ idf\text{(term)}=\frac{n_{\text{documents}}}{n_{\text{documents containing term}}} \]

In this case, \(n_{\text{documents}} = 6\) as we have 6 different parties.

Terms with low tf-idf:

tokens.count %>%
  arrange(tf_idf) 
## # A tibble: 55,124 x 6
##    party     word                n      tf   idf tf_idf
##    <chr>     <chr>           <int>   <dbl> <dbl>  <dbl>
##  1 DIE LINKE bundesregierung   566 0.0109      0      0
##  2 AfD       deutschland       470 0.0128      0      0
##  3 DIE LINKE deutschland       330 0.00637     0      0
##  4 DIE LINKE eu                324 0.00625     0      0
##  5 DIE LINKE menschen          286 0.00552     0      0
##  6 AfD       deutschen         235 0.00641     0      0
##  7 FDP       deutschland       226 0.0109      0      0
##  8 DIE LINKE endlich           219 0.00423     0      0
##  9 AfD       eu                208 0.00567     0      0
## 10 DIE LINKE vorsitzend        208 0.00401     0      0
## # ... with 55,114 more rows

A 0 idf (and thus tf-idf) indicate, that these terms appear in all six parties press-releases.

The inverse document frequency (and thus tf-idf) is very low (0) for terms that occur in many (all) of the documents (all press releases of one party) in a collection (all press releases of one party);

Terms with high tf-idf.

tokens.count %>%
  arrange(desc(tf_idf))
## # A tibble: 55,124 x 6
##    party     word                  n      tf   idf  tf_idf
##    <chr>     <chr>             <int>   <dbl> <dbl>   <dbl>
##  1 AfD       weidel              185 0.00505  1.79 0.00904
##  2 FDP       beer                 59 0.00286  1.79 0.00512
##  3 FDP       nicola               58 0.00281  1.79 0.00503
##  4 AfD       pazderski            98 0.00267  1.79 0.00479
##  5 AfD       alic                145 0.00395  1.10 0.00434
##  6 FDP       lambsdorff           42 0.00203  1.79 0.00364
##  7 DIE LINKE dagdelen            102 0.00197  1.79 0.00353
##  8 FDP       präsidiumsmitgli     57 0.00276  1.10 0.00303
##  9 AfD       brandner             62 0.00169  1.79 0.00303
## 10 FDP       generalsekretärin    54 0.00261  1.10 0.00287
## # ... with 55,114 more rows

N-Grams

Words can be considered not only as single units, but also as their relationship to each other. N-grams, for example, help to investigate which words tend to follow others immediately. To do this, we tokenize the text into successive sequences of words called n-grams. By seeing how often word X is followed by word Y, we can then build a model of the relationships between them.

Bigrams

bigrams <- pressReleases %>% unnest_tokens(bigram, text_cleaned1, token="ngrams", n=2)

bigrams.count <- bigrams %>%
  count(party, bigram, sort = TRUE) %>%
  ungroup() %>%
  bind_tf_idf(bigram,party,n)

Trigrams